<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Canvas Test</title>
    <link href="http://cdn.bootcss.com/bootstrap/3.1.0/css/bootstrap.css" rel="stylesheet">
    <style>
        html, body {
            height: 100%;
            width: 100%;
        }
        .aside {
            display: inline-block;
            vertical-align: top;
            border-right: 1px solid #ccc;
            height: 100%;
        }
        .preview {
            display: inline-block;
            width: 40em;
        }
        #canvas {
            display: inline-block;
            border: 1px solid black;
            border-radius: 1em;
            background: transparent;
            margin-left: 5em;
        }
        input[type="color"] {
            margin-right: 10px;
            width: 3em!important;
        }
        label {
            margin-right: 1em;
        }
        .item {
            margin: 1em;
        }
        #colors {
            margin: 1em 0;
        }
    </style>
    <script>
        function TextPainter(canvas, downLink) {
            this.text = 'Demo';
            this.canvas = ('string' === typeof(canvas)) ? document.getElementById(canvas) : canvas;
            this.canvas && (this.ctx = this.canvas.getContext('2d'));
            this.downLink = ('string' === typeof(downLink)) ? document.getElementById(downLink) : downLink;
            this.colors = ['black'];
        }

        TextPainter.prototype = {
            _setTextStyle: function(){
                var ctx = this.ctx;
                var canvas = this.canvas;
                var len = this.text.length;
                ctx.font = canvas.width / len + "px Verdana bold";
                var gradient=ctx.createLinearGradient(0, 0, canvas.width, 0);
                var step = 0;
                for (var i = 0, l = this.colors.length; i < l; i++) {
                    step = l - 1;
                    (0 === step) && (step = 1);
                    gradient.addColorStop(i / step, this.colors[i]);
                }
                ctx.fillStyle = gradient;
                ctx.textAlign = 'center';
                ctx.textBaseline = 'middle';
            },
            size: function(size){
                var canvas = this.canvas;
                size.width && (canvas.width = size.width);
                size.height && (canvas.height = size.height);
            },
            text: function(text){
                text && (this.text = text);
            },
            picName: function(picName){
                picName && this.downLink.setAttribute('download', picName + '.png');
            },
            gradient: function(colors){
                this.colors = colors;
            },
            refresh: function (text){
                var ctx = this.ctx;
                var canvas = this.canvas;

                !text ? (text = this.text) : (this.text = text);
                this._setTextStyle();
                ctx.clearRect(0, 0, canvas.width, canvas.height);
                ctx.fillText(text , canvas.width / 2, canvas.height / 2);

                this.downLink.href = canvas.toDataURL();
            }
        }

        function handleEvent(callback) {
            return function(e){
                var elem = e.srcElement || e.target;
                callback && ('function' ===  typeof(callback)) && callback(elem);
            };
        }

        window.onload = function() {
            var text = document.getElementById('text');
            var name = document.getElementById('name');
            var width = document.getElementById('width');
            var height = document.getElementById('height');
            var addBtn = document.getElementById('add');
            var applyBtn = document.getElementById('apply');
            var textPainter = new TextPainter('canvas', 'download');

            //bind handlers
            width.oninput = handleEvent(function(elem){
                textPainter.size({width: elem.value});
                textPainter.refresh();
            });

            height.oninput = handleEvent(function(elem){
                textPainter.size({height: elem.value});
                textPainter.refresh();
            });

            text.oninput = handleEvent(function(elem){
                textPainter.refresh(elem.value);
            });

            name.oninput = handleEvent(function(elem){
                textPainter.picName(elem.value);
            });

            addBtn.onclick = handleEvent(function(elem){
                var colorElem = document.createElement('input');
                colorElem.setAttribute('type', 'color');
                colorElem.className = 'form-control';
                elem.nextElementSibling.appendChild(colorElem);
            });

            applyBtn.onclick = handleEvent(function(){
                var colorElems = document.querySelectorAll('input[type="color"]');
                var colors = [];
                [].slice.call(colorElems).forEach(function(colorElem){
                    colors.push(colorElem.value);
                });
                textPainter.gradient(colors);
                textPainter.refresh();
            });

            textPainter.refresh();

        };
    </script>
</head>
<body>
    <div class="aside">
        <div class="form-inline item">
            <label for="text" class="control-label">输入文字</label>
            <input type="text" id="text" class="form-control"/>
        </div>
        <div class="form-inline item">
            <label for="name" class="control-label">导出图片名称</label>
            <input type="text" id="name" class="form-control" value="canvasexport"/>
        </div>
        <div class="form-inline item">
            <label for="width">宽度:</label>
            <input type="number" id="width" min="40" max="400" value="400" class="form-control">
            <label for="height">高度:</label>
            <input type="number" id="height" min="40" max="400" value="400" class="form-control">
        </div>
        <div class="form-group item">
            <label for="width">添加渐变:</label>
            <button id="add" class="btn btn-primary">+</button>
            <div id="colors" class="form-inline">
                <input type="color" class="form-control"/>
            </div>
            <button id="apply" class="btn btn-success">应用渐变</button>
        </div>
    </div>
    <div class="preview">
        <div class="item">
            <label>预览</label><a href="" id="download" download="canvasexport.png" class="btn btn-info">下载</a>
        </div>
        <canvas id="canvas" width="400" height="400"></canvas>
    </div>
</body>
</html>